package com.solution.action;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.upload.FormFile;

import com.solution.constant.LoginConstants;
import com.solution.constant.StatusConstants;
import com.solution.delegate.ExaminationServiceDelegate;
import com.solution.delegate.UserInfoServiceDelegate;
import com.solution.exception.DelegateException;
import com.solution.exception.ServiceBeanException;
import com.solution.form.QuestionForm;
import com.solution.model.AnswerType;
import com.solution.model.CategoryType;
import com.solution.model.ImageType;
import com.solution.model.LevelType;
import com.solution.model.QuestionType;
import com.solution.model.UserInfo;
import com.solution.model.UserQuestionMapping;
import com.solution.util.SearchVO;
import com.solution.webconstant.ExaminationConstant;

public class QuestionAction extends Action{

	/**
	 * logging instance.
	 */
	private Logger logger = Logger.getLogger(QuestionAction.class.getName());

	/**
	 * Date format.
	 */
	private static SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
	
	/**
	 * Default method.
	 */
	public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: QuestionAction:execute()");
		QuestionForm questionForm =(QuestionForm)form;
		request.setAttribute("tab", "QUESTION");

		/**
		 * Creation Case.
		 */
		if("/createQuestion".equals(mapping.getPath())){
			return createQuestion(mapping, questionForm, request, response);
		}
		/**
		 * Search Case.
		 */
		else if("/searchQuestion".equals(mapping.getPath())){
			return searchQuestion(mapping, questionForm, request, response);
		}
		/**
		 * Updation Case.
		 */
		else if("/updateQuestion".equals(mapping.getPath())){
			return updateQuestion(mapping, questionForm, request, response);
		}
		/**
		 * Edit/View Case.
		 */
		else if("/editViewQuestion".equals(mapping.getPath())){
			return editViewQuestion(mapping, questionForm, request, response);
		}
		else if("/uploadQuestionFileScreen".equals(mapping.getPath())){
			return mapping.findForward("uploadScreen");
		}
		else if("/uploadQuestionFile".equals(mapping.getPath())){
			return uploadQuestionFile(mapping, questionForm, request, response);
		}
		else{
			return fetchCategoryLevelList(mapping, questionForm, request, response);
		}
	}

	public ActionForward uploadQuestionFile(ActionMapping mapping,QuestionForm questionForm,HttpServletRequest request, 
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: QuestionAction:uploadQuestionFile()");
		ActionMessages  errors  = new ActionMessages();
		HttpSession session = request.getSession();
		UserInfo userInfo = null;
		if(session != null){
			userInfo = (UserInfo)session.getAttribute(LoginConstants.SESSION_USER_INFO);
		}
		try{
			FormFile file = questionForm.getBulk_questions();
			String outputFileName = file.getFileName().substring(0,file.getFileName().length()-4)+"_Result.xls";
			InputStream xlsStream = file.getInputStream();
			HSSFWorkbook outputFile = createBasicQuestionFile();
			HSSFSheet outputSheet = outputFile.getSheetAt(0);
			HSSFWorkbook wb = new HSSFWorkbook(xlsStream);
			HSSFSheet sheet = wb.getSheetAt(0);
			Iterator<HSSFRow> rows = sheet.rowIterator();
			int recordCount = 0;
			int rowIndex = 1;
			rows.next();//First Line will be headers. So, skip it.
			ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
			while(rows.hasNext()){
				recordCount++;
				HSSFRow row = (HSSFRow) rows.next();
				HSSFRow outputRow = outputSheet.createRow(rowIndex);
				Iterator<HSSFCell> iter = row.cellIterator();
				while(iter.hasNext()){
					HSSFCell cell = (HSSFCell) iter.next();
					if(isDateType(cell)){
						outputRow.createCell(cell.getColumnIndex()).setCellValue(new HSSFRichTextString(dateFormat.format(cell.getDateCellValue())));
					}
					else if(isNumericType(cell)){
						outputRow.createCell(cell.getColumnIndex()).setCellValue(cell.getNumericCellValue());
					}
					else if(isBooleanType(cell)){
						outputRow.createCell(cell.getColumnIndex()).setCellValue(cell.getBooleanCellValue());
					}
					else{
						outputRow.createCell(cell.getColumnIndex()).setCellValue(cell.getRichStringCellValue());
					}
				}
				createQuestionEntry(row, examinationServiceDelegate, userInfo,outputRow);
				rowIndex++;
			}
			File file1 = null;
			File fileTemp = null;
			DataOutputStream dos = null;
			FileOutputStream fos;
			fileTemp= new File("D:/ProductionFiles/QuestionUpload");
			fileTemp.mkdir();
			file1 = new File("D:/ProductionFiles/QuestionUpload/"+outputFileName);
			file1.createNewFile();
			fos = new FileOutputStream(file1);
			dos=new DataOutputStream(fos);
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			outputFile.write(bos);
			dos.write(bos.toByteArray());
			response.setContentType("application/vnd.ms-excel");
			response.setHeader("Content-Disposition","attachment; filename=" +outputFileName);
			ServletOutputStream outputStream = response.getOutputStream();
			outputStream.write(bos.toByteArray());
			outputStream.flush();
			outputStream.close();
			dos.close();
			fos.close();
			return null;
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Question.add.fail"));
		}
		saveErrors(request, errors);
		logger.debug("Exiting :: QuestionAction:uploadQuestionFile()");
		return mapping.findForward("successUploadQuestionFile");
	}
	
	private void createQuestionEntry(HSSFRow row, ExaminationServiceDelegate examinationServiceDelegate, 
			UserInfo userInfo, HSSFRow outputRow) throws DelegateException{
		try{
			Iterator<HSSFCell> cells = row.cellIterator();
			HSSFCell cell;
			QuestionType question = new QuestionType();
			question.setCreatedOn(new Date());
			question.setCreatedBy(userInfo.getUsername());
			question.setStatus(StatusConstants.ACTIVE);
			List<AnswerType> answers = new ArrayList<AnswerType>(5);
			String category = null;
			String level = null;
			String correctAnswer = null;
			String wrongAns = null;
			outputRow.createCell(8).setCellValue(new HSSFRichTextString("Success"));
			while(cells.hasNext()){
				cell = (HSSFCell) cells.next();
				logger.info("The cellIndex is :"+cell.getColumnIndex());
				switch(cell.getColumnIndex()){
					case 0://question statement
						question.setQuestionStatement(cell.getRichStringCellValue().getString().trim());
						break;
					case 1://Category
						category = cell.getRichStringCellValue().getString().trim();
						if(category != null && !"".equals(category)){
							SearchVO searchVO = new SearchVO();
							searchVO.addEqualsIgnoreCaseCondition("name", category);
							List<CategoryType> categories = examinationServiceDelegate.getCategories(searchVO);
							if(categories != null && categories.size()==1){
								question.setCategoryType(categories.get(0));
							}
						}
						break;
					case 2://Level
						level = cell.getRichStringCellValue().getString().trim();
						if(level != null && !"".equals(level)){
							SearchVO searchVO = new SearchVO();
							searchVO.addEqualsIgnoreCaseCondition("name", level);
							List<LevelType> levels = examinationServiceDelegate.getLevels(searchVO);
							if(levels != null && levels.size()==1){
								question.setLevelType(levels.get(0));
							}
						}
						break;
					case 3://correct Answer
						if(isDateType(cell)){
							correctAnswer = dateFormat.format(cell.getDateCellValue());
						}
						else if(isNumericType(cell)){
							correctAnswer = String.valueOf(cell.getNumericCellValue());
						}
						else if(isBooleanType(cell)){
							correctAnswer = String.valueOf(cell.getBooleanCellValue());
						}
						else{
							correctAnswer = cell.getRichStringCellValue().getString().trim();
						}
						if(correctAnswer != null && !"".equals(correctAnswer)){
							AnswerType answer = new AnswerType();
							answer.setAnswerValue(correctAnswer);
							answer.setCreatedBy(userInfo.getUsername());
							answer.setCreatedOn(new Date());
							answer.setIsCorrect(true);
							answer.setStatus(StatusConstants.ACTIVE);
							answers.add(answer);
						}
						break;
					case 4://wrong Answer1
						if(isDateType(cell)){
							wrongAns = dateFormat.format(cell.getDateCellValue());
						}
						else if(isNumericType(cell)){
							wrongAns = String.valueOf(cell.getNumericCellValue());
						}
						else if(isBooleanType(cell)){
							wrongAns = String.valueOf(cell.getBooleanCellValue());
						}
						else{
							wrongAns = cell.getRichStringCellValue().getString().trim();
						}
						if(wrongAns != null && !"".equals(wrongAns)){
							AnswerType answer = new AnswerType();
							answer.setAnswerValue(wrongAns);
							answer.setCreatedBy(userInfo.getUsername());
							answer.setCreatedOn(new Date());
							answer.setIsCorrect(false);
							answer.setStatus(StatusConstants.ACTIVE);
							answers.add(answer);
						}
						break;
					case 5://wrong Answer2
						if(isDateType(cell)){
							wrongAns = dateFormat.format(cell.getDateCellValue());
						}
						else if(isNumericType(cell)){
							wrongAns = String.valueOf(cell.getNumericCellValue());
						}
						else if(isBooleanType(cell)){
							wrongAns = String.valueOf(cell.getBooleanCellValue());
						}
						else{
							wrongAns = cell.getRichStringCellValue().getString().trim();
						}
						if(wrongAns != null && !"".equals(wrongAns)){
							AnswerType answer = new AnswerType();
							answer.setAnswerValue(wrongAns);
							answer.setCreatedBy(userInfo.getUsername());
							answer.setCreatedOn(new Date());
							answer.setIsCorrect(false);
							answer.setStatus(StatusConstants.ACTIVE);
							answers.add(answer);
						}
						break;
					case 6://wrong Answer3
						if(isDateType(cell)){
							wrongAns = dateFormat.format(cell.getDateCellValue());
						}
						else if(isNumericType(cell)){
							wrongAns = String.valueOf(cell.getNumericCellValue());
						}
						else if(isBooleanType(cell)){
							wrongAns = String.valueOf(cell.getBooleanCellValue());
						}
						else{
							wrongAns = cell.getRichStringCellValue().getString().trim();
						}
						if(wrongAns != null && !"".equals(wrongAns)){
							AnswerType answer = new AnswerType();
							answer.setAnswerValue(wrongAns);
							answer.setCreatedBy(userInfo.getUsername());
							answer.setCreatedOn(new Date());
							answer.setIsCorrect(false);
							answer.setStatus(StatusConstants.ACTIVE);
							answers.add(answer);
						}
						break;
					case 7://wrong Answer4
						if(isDateType(cell)){
							wrongAns = dateFormat.format(cell.getDateCellValue());
						}
						else if(isNumericType(cell)){
							wrongAns = String.valueOf(cell.getNumericCellValue());
						}
						else if(isBooleanType(cell)){
							wrongAns = String.valueOf(cell.getBooleanCellValue());
						}
						else{
							wrongAns = cell.getRichStringCellValue().getString().trim();
						}
						if(wrongAns != null && !"".equals(wrongAns)){
							AnswerType answer = new AnswerType();
							answer.setAnswerValue(wrongAns);
							answer.setCreatedBy(userInfo.getUsername());
							answer.setCreatedOn(new Date());
							answer.setIsCorrect(false);
							answer.setStatus(StatusConstants.ACTIVE);
							answers.add(answer);
						}
						break;
				}
			}
			if(question.getQuestionStatement() == null || "".equals(question.getQuestionStatement().trim())){
				outputRow.createCell(8).setCellValue(new HSSFRichTextString("Fail: Question Statement is mandatory"));
				return;
			}
			else if(question.getCategoryType() == null){
				outputRow.createCell(8).setCellValue(new HSSFRichTextString("Fail: Invalid Category"));
				return;
			}
			else if(question.getLevelType() == null){
				outputRow.createCell(8).setCellValue(new HSSFRichTextString("Fail: Invalid Level"));
				return;
			}
			else if(answers == null || answers.size() <= 1){
				outputRow.createCell(8).setCellValue(new HSSFRichTextString("Fail: Atleast two Answer options are madatory"));
				return;
			}
			else{
				Collections.sort(answers,new AnswerCompartor());
				for(AnswerType answer : answers){
					if(answer.getIsCorrect()){
						examinationServiceDelegate.createQuestionAnswer(question, answers);
						return;
					}
				}
				outputRow.createCell(8).setCellValue(new HSSFRichTextString("Fail: Correct answer option is madatory"));
				return;
			}
		}
		catch(ServiceBeanException sbe){
			outputRow.createCell(8).setCellValue(new HSSFRichTextString(sbe.getMessage()));
			return;
		}
	}

	public ActionForward fetchCategoryLevelList(ActionMapping mapping,QuestionForm questionForm,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		ActionMessages  errors  = new ActionMessages() ;
		try{
			ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
			List<CategoryType> categories = examinationServiceDelegate.fetchActiveCategories();
			if(categories != null && categories.size()>0){
				questionForm.setCategories(categories);
			}
			List<LevelType> levels = examinationServiceDelegate.fetchActiveLevels();
			if(levels != null && levels.size() >0){
				questionForm.setLevels(levels);
			}
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Question.fail.exception", sbe.getMessage()));
			questionForm.setScreen_type("");
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Question.add.fail"));
			questionForm.setScreen_type("");
		}
		return mapping.findForward("init");
	}

	public ActionForward createQuestion(ActionMapping mapping,QuestionForm questionForm,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: QuestionAction:createQuestion()");
		ActionMessages messages = new ActionMessages();
		ActionMessages  errors  = new ActionMessages() ;
		HttpSession session = request.getSession();
		UserInfo userInfo = null;
		if(session != null){
			userInfo = (UserInfo)session.getAttribute(LoginConstants.SESSION_USER_INFO);
		}
		QuestionType question=null;
		try{
			ActionMessages guiErrors = questionForm.validate(mapping, request);
			ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
			if(guiErrors!=null && guiErrors.size()>0){
	    		saveErrors(request, guiErrors);
				List<CategoryType> categories = examinationServiceDelegate.fetchActiveCategories();
				if(categories != null && categories.size()>0){
					questionForm.setCategories(categories);
				}
				List<LevelType> levels = examinationServiceDelegate.fetchActiveLevels();
				if(levels != null && levels.size() >0){
					questionForm.setLevels(levels);
				}
				questionForm.setScreen_type("");
	    		return mapping.findForward("createQuestion");
	    	}
			// obtain the PO.
			question = convertFormToPersistentObject(questionForm,request,"add");
			// create the entity in database.
			List<AnswerType> answers = new ArrayList<AnswerType>();
			for(int answerOption =0;answerOption<questionForm.getAnswer_option().length;answerOption++){
				AnswerType answerType = null;
				ImageType image = null;
				Date createdOn = new Date();
				if(questionForm.getAnswer_option()[answerOption]!= null && !"".equals(questionForm.getAnswer_option()[answerOption].trim())){
					answerType = new AnswerType();
						
					switch (answerOption){
					case 0:
						if(questionForm.getAnswer_option_image1()!=null && questionForm.getAnswer_option_image1().getFileSize()>0)
						{
							image = new ImageType();
							image.setCreatedBy(userInfo.getUsername());
							image.setCreatedOn(createdOn);
							image.setOriginalImage(questionForm.getAnswer_option_image1().getFileData());
							image.setTypeId(new Long(1));
						}
						break;
					case 1:
						if(questionForm.getAnswer_option_image2()!=null && questionForm.getAnswer_option_image2().getFileSize()>0)
						{
							image = new ImageType();
							image.setCreatedBy(userInfo.getUsername());
							image.setCreatedOn(createdOn);
							image.setOriginalImage(questionForm.getAnswer_option_image2().getFileData());
							image.setTypeId(new Long(1));
						}
						break;						
					case 2:
						if(questionForm.getAnswer_option_image3()!=null && questionForm.getAnswer_option_image3().getFileSize()>0)
						{
							image = new ImageType();
							image.setCreatedBy(userInfo.getUsername());
							image.setCreatedOn(createdOn);
							image.setOriginalImage(questionForm.getAnswer_option_image3().getFileData());
							image.setTypeId(new Long(1));
						}
						break;
					case 3:
						if(questionForm.getAnswer_option_image4()!=null && questionForm.getAnswer_option_image4().getFileSize()>0)
						{
							image = new ImageType();
							image.setCreatedBy(userInfo.getUsername());
							image.setCreatedOn(createdOn);
							image.setOriginalImage(questionForm.getAnswer_option_image4().getFileData());
							image.setTypeId(new Long(1));
						}
						break;
					case 4:
						if(questionForm.getAnswer_option_image5()!=null && questionForm.getAnswer_option_image5().getFileSize()>0)
						{
							image = new ImageType();
							image.setCreatedBy(userInfo.getUsername());
							image.setCreatedOn(createdOn);
							image.setOriginalImage(questionForm.getAnswer_option_image5().getFileData());
							image.setTypeId(new Long(1));
						}
						break;
					}
					
					answerType.setImageType(image);
					answerType.setAnswerValue(questionForm.getAnswer_option()[answerOption]);
					answerType.setCreatedBy(userInfo.getUsername());
					answerType.setCreatedOn(createdOn);
					
					if((answerOption+1)== questionForm.getIs_correct()){
						answerType.setIsCorrect(true);
					}else{
						answerType.setIsCorrect(false);
					}
					answerType.setStatus(StatusConstants.ACTIVE);
					answers.add(answerType);				
				}
			}
			
			question = examinationServiceDelegate.createQuestionAnswer(question, answers);
			if(question != null){
				messages.add("message", new ActionMessage("Question.add.success"));
				saveMessages(request, messages);
				// set the form parameters for the next navigation.
				if(question.getId() != null){
					questionForm.setQuestion_id(question.getId().longValue()+"");
				}
				if(question.getImageType() != null && question.getImageType().getId() != null){
					questionForm.setQuestion_image_id(question.getImageType().getId().longValue()+"");
				}
				List<CategoryType> categories = examinationServiceDelegate.fetchActiveCategories();
				if(categories != null && categories.size()>0){
					questionForm.setCategories(categories);
				}
				List<LevelType> levels = examinationServiceDelegate.fetchActiveLevels();
				if(levels != null && levels.size() >0){
					questionForm.setLevels(levels);
				}
				List<AnswerType> ansList = examinationServiceDelegate.fetchActiveAnswers(question.getId());
				fillAnswerList(questionForm, ansList);				
				questionForm.setScreen_type(ExaminationConstant.SCREEN_TYPE_VIEW);
			}
			else{
				errors.add("error", new ActionMessage("Question.add.fail"));
				questionForm.setScreen_type("");
			}
		}
		catch(RemoteException re){
			logger.error(re);
			errors.add("error", new ActionMessage("Question.add.fail"));
			questionForm.setScreen_type("");
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Question.fail.exception", sbe.getMessage()));
			questionForm.setScreen_type("");
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Question.add.fail"));
			questionForm.setScreen_type("");
		}
		catch(ParseException pe){
			logger.error(pe);
			errors.add("error", new ActionMessage("Question.add.fail"));
			questionForm.setScreen_type("");
		}
		saveErrors(request, errors);
		logger.debug("Exiting :: QuestionAction:createQuestion()");
		return mapping.findForward("createQuestion");
	}

	public ActionForward searchQuestion(ActionMapping mapping,QuestionForm questionForm,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: QuestionAction:searchQuestion()");
		ActionMessages errors  = new ActionMessages();
		try{
			ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
			if(questionForm.getShow_list() == null || questionForm.getShow_list().equals("")){
				questionForm.setShow_list("N");
			}
			else{
				ActionMessages guiErrors = questionForm.validate(mapping, request);
				if(guiErrors!=null && guiErrors.size()>0){
		    		saveErrors(request, guiErrors);
		    		List<CategoryType> categories = examinationServiceDelegate.fetchActiveCategories();
					if(categories != null && categories.size()>0){
						questionForm.setCategories(categories);
					}
					List<LevelType> levels = examinationServiceDelegate.fetchActiveLevels();
					if(levels != null && levels.size() >0){
						questionForm.setLevels(levels);
					}
					questionForm.setShow_list("N");
		    		return mapping.findForward("searchQuestion");
		    	}
				// filling the search criteria.
				SearchVO searchVO = new SearchVO();
				List<QuestionType> questionList = null;
				if(questionForm.getQuestion_category_id() != null && !questionForm.getQuestion_category_id().equals("")){
					searchVO.addEqualsCondition("categoryType.id", new Long(questionForm.getQuestion_category_id()), true);
				}
				if(questionForm.getQuestion_level_id() != null && !questionForm.getQuestion_level_id().equals("")){
					searchVO.addEqualsCondition("levelType.id", new Long(questionForm.getQuestion_level_id()), true);
				}
				if(questionForm.getQuestion_status() != null && !questionForm.getQuestion_status().equals("")){
					searchVO.addEqualsCondition("status", new Short(questionForm.getQuestion_status()));
				}
				questionList = examinationServiceDelegate.fetchQuestions(searchVO);
				questionForm.setShow_list("Y");
				if(questionList!=null && questionList.size()>0){
					questionForm.setQuestion_list(questionList);
				}
				else{
					errors.add("error", new ActionMessage("Question.search.fail"));
				}
			}
			List<CategoryType> categories = examinationServiceDelegate.fetchActiveCategories();
			if(categories != null && categories.size()>0){
				questionForm.setCategories(categories);
			}
			List<LevelType> levels = examinationServiceDelegate.fetchActiveLevels();
			if(levels != null && levels.size() >0){
				questionForm.setLevels(levels);
			}
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Question.fail.exception", sbe.getMessage()));
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Question.search.fail"));
		}
		saveErrors(request, errors);
		logger.debug("Exiting :: QuestionAction:searchQuestion()");
		return mapping.findForward("searchQuestion");
	}

	public ActionForward updateQuestion(ActionMapping mapping,QuestionForm questionForm,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: QuestionAction:updateQuestion()");
		ActionMessages messages = new ActionMessages();
		ActionMessages errors  = new ActionMessages() ;
		QuestionType question =null;
		HttpSession session = request.getSession();
		UserInfo userInfo = null;
		if(session != null){
			userInfo = (UserInfo)session.getAttribute(LoginConstants.SESSION_USER_INFO);
		}
		try{
			ActionMessages guiErrors = questionForm.validate(mapping, request);
			ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
			if(guiErrors!=null && guiErrors.size()>0){
	    		saveErrors(request, guiErrors);
	    		List<CategoryType> categories = examinationServiceDelegate.fetchActiveCategories();
				if(categories != null && categories.size()>0){
					questionForm.setCategories(categories);
				}
				List<LevelType> levels = examinationServiceDelegate.fetchActiveLevels();
				if(levels != null && levels.size() >0){
					questionForm.setLevels(levels);
				}
	    		questionForm.setScreen_type(ExaminationConstant.SCREEN_TYPE_EDIT);
	    		return mapping.findForward("updateQuestion");
	    	}
			question = convertFormToPersistentObject(questionForm,request,"edit");
			/*Block to check whether any change made or not*/
			List<AnswerType> ansList =examinationServiceDelegate.fetchActiveAnswers(question.getId());
			boolean isChanged = isAnswerOptionChanged(ansList,questionForm);
			/**/
			List<AnswerType> answers = new ArrayList<AnswerType>();
			if(questionForm.getIs_updatable() && isChanged){				
				for(int answerOption =0;answerOption<questionForm.getAnswer_option().length;answerOption++){
					AnswerType answerType = null;
					ImageType image = null;
					Date createdOn = new Date();
					if(questionForm.getAnswer_option()[answerOption]!= null && !"".equals(questionForm.getAnswer_option()[answerOption].trim())){
						answerType = new AnswerType();
							
						switch (answerOption){
						case 0:
							if(questionForm.getAnswer_option_image1()!=null && questionForm.getAnswer_option_image1().getFileSize()>0)
							{
								image = new ImageType();
								image.setCreatedBy(userInfo.getUsername());
								image.setCreatedOn(createdOn);
								image.setOriginalImage(questionForm.getAnswer_option_image1().getFileData());
								image.setTypeId(new Long(1));
							}
							break;
						case 1:
							if(questionForm.getAnswer_option_image2()!=null && questionForm.getAnswer_option_image2().getFileSize()>0)
							{
								image = new ImageType();
								image.setCreatedBy(userInfo.getUsername());
								image.setCreatedOn(createdOn);
								image.setOriginalImage(questionForm.getAnswer_option_image2().getFileData());
								image.setTypeId(new Long(1));
							}
							break;						
						case 2:
							if(questionForm.getAnswer_option_image3()!=null && questionForm.getAnswer_option_image3().getFileSize()>0)
							{
								image = new ImageType();
								image.setCreatedBy(userInfo.getUsername());
								image.setCreatedOn(createdOn);
								image.setOriginalImage(questionForm.getAnswer_option_image3().getFileData());
								image.setTypeId(new Long(1));
							}
							break;
						case 3:
							if(questionForm.getAnswer_option_image4()!=null && questionForm.getAnswer_option_image4().getFileSize()>0)
							{
								image = new ImageType();
								image.setCreatedBy(userInfo.getUsername());
								image.setCreatedOn(createdOn);
								image.setOriginalImage(questionForm.getAnswer_option_image4().getFileData());
								image.setTypeId(new Long(1));
							}
							break;
						case 4:
							if(questionForm.getAnswer_option_image5()!=null && questionForm.getAnswer_option_image5().getFileSize()>0)
							{
								image = new ImageType();
								image.setCreatedBy(userInfo.getUsername());
								image.setCreatedOn(createdOn);
								image.setOriginalImage(questionForm.getAnswer_option_image5().getFileData());
								image.setTypeId(new Long(1));
							}
							break;
						}
						
						answerType.setImageType(image);
						answerType.setAnswerValue(questionForm.getAnswer_option()[answerOption]);
						answerType.setCreatedBy(userInfo.getUsername());
						answerType.setCreatedOn(createdOn);
						
						if((answerOption+1)== questionForm.getIs_correct()){
							answerType.setIsCorrect(true);
						}else{
							answerType.setIsCorrect(false);
						}
						answerType.setStatus(StatusConstants.ACTIVE);
						answers.add(answerType);				
					}
				}			
				
			}
			question = examinationServiceDelegate.updateQuestionAnswer(question, answers);
			
			if(question != null){
				messages.add("message", new ActionMessage("Question.update.success"));
				saveMessages(request, messages);
				// set the form parameters for the next navigation.
				if(question.getId() != null){
					questionForm.setQuestion_id(question.getId().longValue()+"");
				}
				if(question.getImageType() != null && question.getImageType().getId() != null){
					questionForm.setQuestion_image_id(question.getImageType().getId().longValue()+"");
				}
				questionForm.setQuestion_statement(question.getQuestionStatement());
				List<CategoryType> categories = examinationServiceDelegate.fetchActiveCategories();
				if(categories != null && categories.size()>0){
					questionForm.setCategories(categories);
				}
				List<LevelType> levels = examinationServiceDelegate.fetchActiveLevels();
				if(levels != null && levels.size() >0){
					questionForm.setLevels(levels);
				}
				fillAnswerList(questionForm, examinationServiceDelegate.fetchActiveAnswers(question.getId()));
				questionForm.setScreen_type(ExaminationConstant.SCREEN_TYPE_VIEW);
			}
			else{
				errors.add("error", new ActionMessage("Question.update.fail"));
				questionForm.setScreen_type(ExaminationConstant.SCREEN_TYPE_EDIT);
			}
		}
		catch(RemoteException re){
			logger.error(re);
			errors.add("error", new ActionMessage("Question.update.fail"));
			questionForm.setScreen_type(ExaminationConstant.SCREEN_TYPE_EDIT);
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Question.fail.exception", sbe.getMessage()));
			questionForm.setScreen_type(ExaminationConstant.SCREEN_TYPE_EDIT);
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Question.update.fail"));
			questionForm.setScreen_type(ExaminationConstant.SCREEN_TYPE_EDIT);
		}
		catch(ParseException pe){
			logger.error(pe);
			errors.add("error", new ActionMessage("Question.add.fail"));
			questionForm.setScreen_type(ExaminationConstant.SCREEN_TYPE_EDIT);
		}
		saveErrors(request, errors);
		logger.debug("Exiting :: QuestionAction:updateQuestion()");
		return mapping.findForward("updateQuestion");
	}

	private  boolean  isAnswerOptionChanged(List<AnswerType> ansList, QuestionForm questionForm) {
		boolean isChanged= false;
		int numberOfOptions =0;
		if(questionForm.getAnswer_option()!=null){
			for(int answerOption=0;answerOption<questionForm.getAnswer_option().length;answerOption++){			
				if(questionForm.getAnswer_option()[answerOption]!= null && !"".equals(questionForm.getAnswer_option()[answerOption].trim())){
					numberOfOptions++;
					if(ansList.get(answerOption)!=null && !ansList.get(answerOption).getAnswerValue().equals(questionForm.getAnswer_option()[answerOption].trim())){
						isChanged = true;
					}
					if(ansList.get(answerOption)!=null){
						if(ansList.get(answerOption).getIsCorrect()){
							if((answerOption+1)!= questionForm.getIs_correct()){
								isChanged=true;
							}
						}						
					}
				}
			}
		}
		if((questionForm.getAnswer_option_image1()!=null && questionForm.getAnswer_option_image1().getFileSize()>0)
				|| (questionForm.getAnswer_option_image2()!=null && questionForm.getAnswer_option_image2().getFileSize()>0)
				|| (questionForm.getAnswer_option_image3()!=null && questionForm.getAnswer_option_image3().getFileSize()>0 )
				|| (questionForm.getAnswer_option_image4()!=null && questionForm.getAnswer_option_image4().getFileSize()>0)
				|| (questionForm.getAnswer_option_image5()!=null && questionForm.getAnswer_option_image5().getFileSize()>0)){
			isChanged = true;			
		}
		if(ansList.size()!= numberOfOptions){
			isChanged=true;
		}
		
		return isChanged;
		
	}

	public ActionForward editViewQuestion(ActionMapping mapping,QuestionForm questionForm,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: QuestionAction:editViewQuestion()");
		ActionMessages errors  = new ActionErrors() ;
		try{
			if(questionForm.getQuestion_id() != null && !questionForm.getQuestion_id().equals("")){
				ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
				List<CategoryType> categories = examinationServiceDelegate.fetchActiveCategories();
				if(categories != null && categories.size()>0){
					questionForm.setCategories(categories);
				}
				List<LevelType> levels = examinationServiceDelegate.fetchActiveLevels();
				if(levels != null && levels.size() >0){
					questionForm.setLevels(levels);
				}
				QuestionType question =examinationServiceDelegate.fetchQuestion(new Long(questionForm.getQuestion_id()));
				//fill the form for displaying the details.
				if(question != null){
					questionForm.setQuestion_statement(question.getQuestionStatement());
					if(question.getCategoryType() != null){
						questionForm.setQuestion_category_id(question.getCategoryType().getId().longValue()+"");
					}
					if(question.getLevelType() != null){
						questionForm.setQuestion_level_id(question.getLevelType().getId().longValue()+"");
					}
					if(question.getStatus() != null){
						questionForm.setQuestion_status(question.getStatus().shortValue()+"");
					}
					if(question.getImageType() != null && question.getImageType().getId() != null){
						questionForm.setQuestion_image_id(question.getImageType().getId().longValue()+"");
					}
					List<AnswerType> ansList =examinationServiceDelegate.fetchActiveAnswers(question.getId());
					fillAnswerList(questionForm, ansList);
					boolean isUpdatable = isUpdatable(question.getId(),ansList);
					questionForm.setIs_updatable(isUpdatable);
				}
				else{
					errors.add("error", new ActionMessage("Question.details.fail"));
				}
			}
			else{
				errors.add("error", new ActionMessage("Question.details.fail"));
			}
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Question.fail.exception", sbe.getMessage()));
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Question.details.fail"));
		}
		saveErrors(request, errors);
		logger.debug("Exiting :: QuestionAction:editViewQuestion()");
		return mapping.findForward("editViewQuestion");
	}
	private boolean isUpdatable(Long questionId,List<AnswerType> ansList){
		ActionMessages errors  = new ActionErrors() ;
		boolean isUpdatable = false;
		try{			
		
		UserInfoServiceDelegate userService = new UserInfoServiceDelegate();
		List<Long> andIdList = new ArrayList<Long>(ansList.size());
		for(AnswerType ansType:ansList){
			andIdList.add(ansType.getId());
		}
		SearchVO searchVO = new SearchVO();
		searchVO.addInCondition("answerType", ansList);
		List<UserQuestionMapping> questionMappingList = userService.searchUserQuestionMappings(searchVO);
		
		if(questionMappingList!=null && questionMappingList.size()>0){
			isUpdatable =  false;
		}else{
			isUpdatable =  true;
		}
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Question.fail.exception", sbe.getMessage()));
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Question.details.fail"));
		}
		return isUpdatable;
	}

	private void fillAnswerList(QuestionForm questionForm, List<AnswerType> answers){
		String[] ansStatement = new String[answers.size()];
		int i=0;
		for(AnswerType answerType : answers){
			ansStatement[i] = answerType.getAnswerValue();
			if(answerType.getIsCorrect()){
				questionForm.setIs_correct(i+1);
			}
			if(answerType.getImageType() != null && answerType.getImageType().getOriginalImage() != null){
				switch(i){
					case 0:
						questionForm.setAnswer_option_image1_id(answerType.getImageType().getId().toString());
						break;
					case 1:
						questionForm.setAnswer_option_image2_id(answerType.getImageType().getId().toString());
						break;
					case 2:
						questionForm.setAnswer_option_image3_id(answerType.getImageType().getId().toString());
						break;
					case 3:
						questionForm.setAnswer_option_image4_id(answerType.getImageType().getId().toString());
						break;
					case 4:
						questionForm.setAnswer_option_image5_id(answerType.getImageType().getId().toString());
						break;
				}
			}
			i++;
		}
		questionForm.setAnswer_option(ansStatement);
	}
	
	private QuestionType convertFormToPersistentObject(QuestionForm questionForm,
			HttpServletRequest request,String pageType) throws ServiceBeanException, DelegateException, IOException, ParseException {
		logger.debug("Entering :: QuestionAction:convertFormToPersistentObject()");
		HttpSession session = request.getSession();
		UserInfo userInfo = null;
		if(session != null){
			userInfo = (UserInfo)session.getAttribute(LoginConstants.SESSION_USER_INFO);
		}
		// Creation case.
		QuestionType question = new QuestionType();
		ImageType image = null;
		// modification case.
		ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
		if("edit".equalsIgnoreCase(pageType)){
			logger.info("Update case for the question :"+questionForm.getQuestion_id());
			question = examinationServiceDelegate.fetchQuestion(new Long(questionForm.getQuestion_id().trim()));
			image = question.getImageType();
		}
	    // filling the persistent object.
		if(questionForm.getQuestion_statement()!=null && !"".equals(questionForm.getQuestion_statement())){
			question.setQuestionStatement(questionForm.getQuestion_statement());
		}
		if(questionForm.getQuestion_category_id() != null && !questionForm.getQuestion_category_id().trim().equals("")){
			CategoryType category = examinationServiceDelegate.getCategory(new Long(questionForm.getQuestion_category_id()));
			question.setCategoryType(category);
		}
		if(questionForm.getQuestion_level_id() != null && !questionForm.getQuestion_level_id().trim().equals("")){
			LevelType level = examinationServiceDelegate.getLevel(new Long(questionForm.getQuestion_level_id()));
			question.setLevelType(level);
		}
		if(questionForm.getQuestion_status() != null && !questionForm.getQuestion_status().trim().equals("")){
			question.setStatus(new Short(questionForm.getQuestion_status().trim()));
		}
	    // image upload function.
		if(questionForm.getQuestion_image()!=null){
		    FormFile myFile = questionForm.getQuestion_image();
		    if(myFile != null && myFile.getFileSize() > 0){
		    	image = new ImageType();
		    	image.setOriginalImage(myFile.getFileData());
		    	image.setTypeId(new Long(1));
				if(userInfo != null){
					image.setCreatedBy(userInfo.getUsername());
				}
				image.setCreatedOn(new Date());
		    }
		}
	    // creation case.
		if("add".equalsIgnoreCase(pageType)){
			if(userInfo != null){
				question.setCreatedBy(userInfo.getUsername());
			}
			question.setCreatedOn(new Date());
		}
		// modification case.
		else{
			if(userInfo != null){
				question.setModifiedBy(userInfo.getUsername());
			}
			question.setModifiedOn(new Date());
			if(image != null){
				if(userInfo != null){
					image.setModifiedBy(userInfo.getUsername());
				}
				image.setModifiedOn(new Date());
			}
		}
		question.setImageType(image);
		logger.debug("Exiting :: QuestionAction:convertFormToPersistentObject()");
		return question;
	}
	
	/**
	 * This method creates the file format.
	 * @return
	 */
	private HSSFWorkbook createBasicQuestionFile(){
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet();
		HSSFRow row = sheet.createRow(0);
		row.createCell(0).setCellValue(new HSSFRichTextString("Question Statement"));
		row.createCell(1).setCellValue(new HSSFRichTextString("Category"));
		row.createCell(2).setCellValue(new HSSFRichTextString("Level"));
		row.createCell(3).setCellValue(new HSSFRichTextString("Correct Answer"));
		row.createCell(4).setCellValue(new HSSFRichTextString("Wrong Answer1"));
		row.createCell(5).setCellValue(new HSSFRichTextString("Wrong Answer2"));
		row.createCell(6).setCellValue(new HSSFRichTextString("Wrong Answer3"));
		row.createCell(7).setCellValue(new HSSFRichTextString("Wrong Answer4"));
		row.createCell(8).setCellValue(new HSSFRichTextString("Result"));
		return workbook;
	}
	
	private  boolean isNumericType(HSSFCell cell){
		return HSSFCell.CELL_TYPE_NUMERIC == cell.getCellType() && !HSSFDateUtil.isCellDateFormatted(cell);
	}
	 
	private  boolean isDateType(HSSFCell cell){
		return HSSFCell.CELL_TYPE_NUMERIC == cell.getCellType() && HSSFDateUtil.isCellDateFormatted(cell);
	}
	private  boolean isBooleanType(HSSFCell cell){
		return HSSFCell.CELL_TYPE_BOOLEAN == cell.getCellType();
	}
	class AnswerCompartor implements Comparator<AnswerType>{

		@Override
		public int compare(AnswerType a1, AnswerType a2) {			
			return a1.getAnswerValue().compareTo(a2.getAnswerValue());
		}
		
	}
}
